#include <kernel/kobject.h>
#include <kernel/initcall.h>
#include <kernel/syslog.h>
#include <mm/mem.h>
#include <drivers/platform.h>
#include <drivers/spi.h>
#include <kernel/fdt.h>

void x86_64_spi_setup(struct spi_device *spi)
{
    struct spi_master *master = spi->master;
    uint64_t spi_base = (uint64_t)master->io_base;
}


int x86_64_spi_transfer(struct spi_device *spi, struct spi_transfer *xfer)
{

}

void x86_64_spi_set_cs(struct spi_device *spi, bool enable)
{

}


static int x86_64_spi_driver_probe(struct platform_device *dev)
{
    fdt_node_t *spi_node= dev->device.dt_node;
    struct spi_gpio gpio_pin;

    if(spi_master_get_gpio_from_fdt(spi_node, &gpio_pin)) {
        return -1;
    }

    size_t irq_num = 0;
    if(fdt_read_prop_int(spi_node, "interrupts", &irq_num)) {
        PLATFORM_SYSLOG_INFO("spi: no interrupts property");
    }

    struct spi_master *master = kmalloc(sizeof(struct spi_master));
    if(master == NULL) {
        PLATFORM_SYSLOG_ERROR("spi: kmalloc failed\n");
        return -1;
    }

    master->io_base = dev->io_base;
    master->set_cs = x86_64_spi_set_cs;
    master->setup = x86_64_spi_setup;
    master->transfer = x86_64_spi_transfer;
    master->pin = gpio_pin;

    platform_set_platform_data(dev, master);

    fdt_node_t *child =  NULL;
    fdt_for_each_node_child(spi_node, child) {
        struct spi_device *spi_dev = kmalloc(sizeof(struct spi_device));
        if(spi_dev == NULL) {
            PLATFORM_SYSLOG_ERROR("spi: kmalloc failed");
            return -1;
        }

        if(spi_device_get_config_from_fdt(child, spi_dev)) {
            kfree(spi_dev);
            return -1;
        }

        if(spi_device_register(spi_dev)) {
            PLATFORM_SYSLOG_ERROR("spi: spi_device_register failed");
            return -1;
        }

        spi_dev->master = master;

        if(irq_num) {
            spi_dev->irq_num = irq_num;
        }
    }

    return 0;
}


static void x86_64_spi_driver_remove(struct platform_device *dev)
{

}


static struct of_device_id x86_64_spi_driver_match[] = {
    {.compatible = "x86_64-spi", .data = "x86_64-spi" },
    { }
};


static struct platform_driver x86_64_spi_pdrv = {
    .driver = {
        .name = "x86_64-spi",
        .of_match_table = x86_64_spi_driver_match,
    },
    .probe = x86_64_spi_driver_probe,
    .remove = x86_64_spi_driver_remove,
};


static int x86_64_spi_driver_register(void)
{
    return platform_driver_register(&x86_64_spi_pdrv);
}


driver_initcall(x86_64_spi_driver_register);
